#include "grasp.h"
//TEST
   #include <cstdlib> 
   #include <ctime> 
//ENDTEST

   

Grasp::Grasp () {}

/** Constructor
* @param listado de los rectángulos a empaquetar
* */
Grasp::Grasp(list<Rectangulo> lista): Heuristica (lista) {
          cout << "GRASP::Constructor(listado) con lista de tamaño= " << lista.size() << endl;
          candidatos = lista;
	  solucion.clear();
          iteracion = iteracionSinCambio = 0;
          mejorSol = INT_MAX;
	  k = (lista.size()*15)/100;     
          srand(time(NULL));
}


void Grasp:: Cardinalidad(int momento) {
   candidatos.sort(); // Se ordenan los candidatos según su área
//   list <Rectangulo> mejores;
   list <Rectangulo>:: iterator it = candidatos.end();
//   it--;
   // Escogemos un candidato al azar entre los k mejores (previamente ordenado).
   int random_integer = (rand()%k)+ (candidatos.size()-k);
   it = candidatos.begin();
   for (int i = 0; i < random_integer; i++)
     it++;
   // Rotará o no los rectángulos si vamos a mejorar la solución
   if (momento >1) {
      int giroAlea = rand() % 100;
      if (giroAlea > 50) //Escogemos al azar si ponerlo girado o no
         it->rotar();
   }
   aSolucion(it);
}

void Grasp:: Rango(int momento) {
   list <Rectangulo> mejores;
   list <Rectangulo>:: iterator it,max = candidatos.end();
   // Candidato máximo =  último en la lista.
   int areamax = (*max).geth()*(*max).getw();
   // Constante = (1-alfa)*mejor.
   float constante = (1 - alfa)*areamax;
   Rectangulo r = (*max);
   // El rectángulo mayor estará sí o sí en la solución.
   mejores.push_back(r); 
   it--;
   // Calculamos el área de los siguientes rectángulos.
   
   float area = (*it).geth()*(*it).getw();
   while (area >= constante){
      Rectangulo a = (*it);
      mejores.push_back(a);
      it--;
      area = (*it).geth()*(*it).getw();
   }
   //Escogemos un candidato al azar.
   int tam = mejores.size();
   int elegido = rand() % tam;
   it = mejores.begin();
   for (int i = 0; i < tam; i++)
     it++;
   // Rotará o no los rectángulos si vamos a mejorar la solución
   if (momento >1) {
      int giroAlea = rand() % 100;
      if (giroAlea > 50) //Escogemos al azar si ponerlo girado o no
         it->rotar();
   }
   aSolucion(it);
}

void Grasp:: Interseccion(int momento) {
//   list <Rectangulo> mejores;
   list <Rectangulo>:: iterator it,max = candidatos.end();
   //Procedimiento para hallar el Rango.
   int areamax = (*max).geth()*(*max).getw();
   float constante = (1 - alfa)*areamax;
   Rectangulo r = (*max);
//   mejores.push_back(r);
   it--;
   float area = (*it).geth()*(*it).getw();
   //Hacemos cardinalidad.
   int i;
   for (i = 0; i < k; i++) {
      if (area >= constante){ 
	// Si su área no es lo suficientemente grande se sale
         //Rectangulo a = (*it);
         //mejores.push_back(a);
         it--;
	 area = (*it).geth()*(*it).getw();
      }
      else 
         break;
   }
   //Escogemos un candidato al azar.
//   int tam = mejores.size();
   int elegido = (rand()%i)+ (candidatos.size()-i);
   it = candidatos.begin();
   for (i = 0; i < elegido; i++)
     it++;
   cout << "Este es el rectángulo elegido" << endl;
   cout << "Rectangulo id= " << (*it).getid() << "  h: "<< (*it).geth() << "  w: " << (*it).getw() << endl;
   // Rotará o no los rectángulos si vamos a mejorar la solución
   if (momento >1) {
      int giroAlea = rand() % 100;
      if (giroAlea > 50) //Escogemos al azar si ponerlo girado o no
         it->rotar();
   }
  aSolucion(it);
  
}

list<Rectangulo> Grasp::generaInicial() {
   while (!candidatos.empty()) {
      Cardinalidad(1);
      //Rango(1);
      //Interseccion(1);
   }
   return solucion;
}


list<Rectangulo> Grasp::mejoraSolucion() {
 // generaInicial(); //preprocesamiento
  reiniciaSolucion();
   while (!candidatos.empty()) {
      Cardinalidad(2);
      //Rango(2);
      //Interseccion(2);
   }
  return solucion;
}
